package com.oocl.im.server;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.oocl.im.packet.MsgPackage;
import com.oocl.im.packet.Operation;

class ServerSocketThread implements Runnable {
	private String name;
	private Socket socket;
	private ObjectInputStream in;
	private ObjectOutputStream out;
	private HashMap<String, ServerSocketThread> userThread;
	private HashMap<String, Boolean> userOn;

	public ServerSocketThread(String name, Socket socket, ObjectInputStream in,
			ObjectOutputStream out,
			HashMap<String, ServerSocketThread> userSocket,
			HashMap<String, Boolean> userOn) throws Exception {
		super();
		this.name = name;
		this.socket = socket;
		this.in = in;
		this.out = out;
		this.userThread = userSocket;
		this.userOn = userOn;
	}

	public ObjectInputStream getIn() {
		return in;
	}

	public ObjectOutputStream getOut() {
		return out;
	}

	@Override
	public void run() {
		try {
			notifyInfo();
			while (true) {
				MsgPackage msg = (MsgPackage) in.readObject();
				switch (msg.getOpeartion()) {
				case CHAT:
					String seneder = msg.getSender();
					if (msg.getReceiver().equals("all")) {
						synchronized (userOn) {
							for (Map.Entry<String, ServerSocketThread> entry : userThread
									.entrySet()) {
								boolean on = entry.getValue() != null;
								boolean isSelf = entry.getKey().equals(
										msg.getSender());
								if (on && !isSelf) {
									entry.getValue().getOut().writeObject(msg);
								}
							}
						}
					} else {
						synchronized (userOn) {
							ServerSocketThread sst = userThread.get(msg
									.getReceiver());
							if (sst != null) {
								sst.getOut().writeObject(msg);
							} else {
								System.out
										.println("can not send message,receiver is offline");
							}
						}
					}
					break;
				case SHAKE:
					if (msg.getReceiver().equals("all")) {
						System.out.println("cannot shake all people");
					} else {
						synchronized (userOn) {
							ServerSocketThread sst = userThread.get(msg
									.getReceiver());
							if (sst != null) {
								sst.getOut().writeObject(msg);
							} else {
								System.out
										.println("cannot shake because receiver offline");
							}

						}
					}
					break;
				case EXIT:
					System.out.println(name + "exit");
					synchronized (userOn) {
						userOn.put(name, false);
						userThread.put(name, null);
					}
					notifyInfo();
					return;
				default:
					break;
				}
			}

		} catch (SocketException E) {
			synchronized (userOn) {
				userOn.put(name, false);
				userThread.put(name, null);
			}
			try {
				notifyInfo();
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println(name + "exit");
		} catch (Exception e) {
			synchronized (userOn) {
				userOn.put(name, false);
				userThread.put(name, null);
			}
			try {
				notifyInfo();
				socket.close();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}

	public void notifyInfo() throws Exception {

		synchronized (userOn) {
			HashMap<String, Boolean> userOn2 = new HashMap<>(userOn);
			MsgPackage msg = new MsgPackage(Operation.NOTIFY, null, null, null,
					null, userOn2);
			for (Entry<String, ServerSocketThread> entry : userThread
					.entrySet()) {
				if (entry.getValue() != null) {
					entry.getValue().out.writeObject(msg);
				}
			}
		}

	}
}